package com.hxs.hxsserver.utils;

import com.hxs.hxsserver.exception.TokenInvalidException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTokenUtil {

    // Secret key for signing the JWT
    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    // Token validity in milliseconds (e.g., 1 hour)
    private static final long TOKEN_VALIDITY = 24 * 60 * 60 * 1000;

    /**
     * Generate JWT token with given username and user ID.
     *
     * @param userId   the user ID to include in the token
     * @param email the email to include in the token
     * @return the generated JWT token
     */
    public static String generateToken(Integer userId, String email) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId); // Adding user ID as a custom claim
        return createToken(claims, email);
    }

    /**
     * Create JWT token.
     *
     * @param claims   the custom claims to include
     * @param subject  the subject (e.g., username)
     * @return the JWT token as a String
     */
    private static String createToken(Map<String, Object> claims, String subject) {
        Date now = new Date();
        Date expiration = new Date(now.getTime() + TOKEN_VALIDITY);

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(now)
                .setExpiration(expiration)
                .signWith(SECRET_KEY)
                .compact();
    }

    /**
     * Parse and validate the JWT token.
     *
     * @param token the JWT token to parse
     * @return the claims extracted from the token
     * @throws SignatureException if the token signature is invalid
     * @throws io.jsonwebtoken.ExpiredJwtException if the token is expired
     */
    public static Claims parseToken(String token) {
        try {
            Jws<Claims> jwsClaims = Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build()
                    .parseClaimsJws(token);

            // Extract claims from the token
            return jwsClaims.getBody();
        } catch (Exception e) {
            throw new TokenInvalidException();
        }
    }
}
